package com.itranswarp.weibo.api;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Map;

/**
 * API invocation handler that makes API call to REST-RPC.
 * 
 * @author Michael Liao (askxuefeng@gmail.com)
 */
class ApiInvocationHandler implements InvocationHandler {

	static final Map<String, ApiInvocation> apiMap = ApiLoader.initApiMap();

	static final Object[] EMPTY_OBJECT_ARRAY = new Object[0];

	final String apiPrefix;
	final AccessToken accessToken;

	ApiInvocationHandler(String apiPrefix, AccessToken accessToken) {
		this.apiPrefix = apiPrefix;
		this.accessToken = accessToken;
	}

	public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
		accessToken.assertNotExpired();
		ApiInvocation api = apiMap.get(method.getName());
		if (api==null)
			throw new WeiboException("API not found in client (need update source code?)");
		ApiParam[] params = api.params;
		if (args==null)
			args = EMPTY_OBJECT_ARRAY;
		if (args.length > params.length)
			throw new WeiboException("Too many args (bad code generation?)");
		// build and check parameters:
		Map<String, Object> actualArgs = new HashMap<String, Object>(params.length);
		for (int i=0; i<params.length; i++) {
			ApiParam p = params[i];
			if (i < args.length) {
				p.checkArg(args[i]);
				actualArgs.put(p.name, args[i]);
			}
			else {
				if ( ! p.optional)
					throw new WeiboException("Arg[" + i + "] " + p.name + " is not optional.");
				actualArgs.put(p.name, p.value);
			}
		}
		Object o = Utils.httpRequest(api.httpMethod, apiPrefix + api.url + ".json", accessToken.authorization, actualArgs, false);
		Utils.checkError(o);
		return o;
	}

}
